﻿using System;
using System.Web;
using System.Collections.Generic;
using System.Web.Mvc;
using System.Web.Security;
using System.Web.Script.Serialization;
using System.Linq;

using MvcCms.Data;
using MvcCms.Service.Filters;
using MvcCms.Service.Code.Email;
using MvcCms.Service;
using MvcCms.Store.Web.ViewModels;
using MvcCms.Data.Entities;
using MvcCms.Service.Code.Encryption;
using MvcCms.Service.Code;


using MvcCms.Store.Service;
using MvcCms.Store.Web.Code;
using AutoMapper;
using MvcCms.Service.Cache;

namespace MvcCms.Store.Web.Code
{
    public partial class ShoppingCart
    {
        string ShoppingCartID { get; set; }
        public const string CartSessionKey = "CartID";

        #region Constructors
        private readonly IStoreService _storeService;
        private readonly ICacheService _cacheService;
        public ShoppingCart(ICacheService cacheService, IStoreService storeService)
        {
            _storeService = storeService;
            _cacheService = cacheService;
        }
        #endregion

        public ShoppingCart GetCart(HttpContextBase context)
        {
            var cart = new ShoppingCart(_cacheService, _storeService);
            cart.ShoppingCartID = cart.GetCartID(context);
            return cart;
        }

        // Helper method to simplify shopping cart calls
        public ShoppingCart GetCart(Controller controller)
        {
            return GetCart(controller.HttpContext);
        }

        public void AddToCart(StoreProduct product, StorePricingOption priceOption, string orderNotes)
        {
            // Get the matching cart and album instances            
            var cartItems = _storeService.GetCart(ShoppingCartID).ToList();
            var cartItem = cartItems.Where(ci => ci.ProductID == product.ProductID && ci.PriceOptionID == priceOption.PriceOptionID).FirstOrDefault();

            if (priceOption.RequiresNotes) { cartItem = null; }

            if (cartItem == null)
            {
                var portal = _cacheService.GetCurrentPortal();
                // Create a new cart item if no cart item exists
                cartItem = new StoreCart
                {
                    ProductID = product.ProductID,
                    CartID = ShoppingCartID,
                    Count = 1,
                    DateCreated = DateTime.Now,
                    PortalID = portal.PortalID,
                    PriceOptionID = priceOption.PriceOptionID,
                    OrderNotes = orderNotes
                };

                cartItems.Add(cartItem);
                _storeService.CreateCart(cartItem);
            }
            else
            {
                // If the item does exist in the cart, then add one to the quantity
                cartItem.Count++;
                if (!string.IsNullOrEmpty(orderNotes))
                {
                    cartItem.OrderNotes += " /Order:" + cartItem.Count + " " + orderNotes;
                }
                _storeService.EditCartItem(cartItem);
            }
        }

        public void AddToCart(StoreProduct product)
        {
            // Get the matching cart and album instances            
            var cartItems = _storeService.GetCart(ShoppingCartID).ToList();
            var cartItem = cartItems.Where(ci => ci.ProductID == product.ProductID).FirstOrDefault();

            if (cartItem == null)
            {
                var portal = _cacheService.GetCurrentPortal();
                // Create a new cart item if no cart item exists
                cartItem = new StoreCart
                {
                    ProductID = product.ProductID,
                    CartID = ShoppingCartID,
                    Count = 1,
                    DateCreated = DateTime.Now,
                    PortalID = portal.PortalID
                };

                cartItems.Add(cartItem);
                _storeService.CreateCart(cartItem);
            }
            else
            {
                // If the item does exist in the cart, then add one to the quantity
                cartItem.Count++;
                _storeService.EditCartItem(cartItem);
            }
            
        }

        public int RemoveFromCart(int id)
        {
            // Get the cart
            var cartItems = _storeService.GetCart(ShoppingCartID).ToList();
            var cartItem = cartItems.Where(ci => ci.RecordID == id && ci.CartID == ShoppingCartID).FirstOrDefault();

            int itemCount = 0;

            if (cartItem != null)
            {
                if (cartItem.Count > 1)
                {
                    cartItem.Count--;
                    itemCount = cartItem.Count;
                    _storeService.EditCartItem(cartItem);
                }
                else
                {
                    _storeService.DeleteCartItem(cartItem);
                }                                
            }

            return itemCount;
        }

        public void EmptyCart()
        {
            var cartItems = _storeService.GetCart(ShoppingCartID).ToList();

            foreach (var cartItem in cartItems)
            {
                _storeService.DeleteCartItem(cartItem);
            }
        }

        public List<StoreCart> GetCartItems()
        {
            return _storeService.GetCart(ShoppingCartID).ToList(); 
        }

        public int GetCount()
        {
            var cartItems = _storeService.GetCart(ShoppingCartID).ToList();
            // Get the count of each item in the cart and sum them up
            int? count = (from item in cartItems
                          where item.CartID == ShoppingCartID
                          select (int?)item.Count).Sum();

            // Return 0 if all entries are null
            return count ?? 0;
        }

        public decimal GetTotal()
        {
            var cartItems = _storeService.GetCartWithProduct(ShoppingCartID).ToList();
            decimal total = 0m;
            foreach (var cartItem in cartItems)
            {
                if (cartItem.PricingOption == null)
                {
                    total += cartItem.Count * cartItem.Product.Price;
                }
                else
                {
                    total += cartItem.Count * decimal.Parse(cartItem.PricingOption.Price.ToString());
                }
            }
            return total;
        }

        public int CreateOrder(StoreOrder order)
        {
            decimal orderTotal = 0;
            var cartItems = _storeService.GetCartWithProduct(ShoppingCartID).ToList();
            var orderNotes = "";
            foreach (var item in cartItems)
            {
                var orderDetail = new StoreOrderDetail
                {
                    ProductID = item.ProductID,
                    OrderID = order.OrderID,
                    Quantity = item.Count,
                    PriceOptionID = item.PriceOptionID
                };

                if (item.PriceOptionID.HasValue)
                {
                    orderDetail.UnitPrice = decimal.Parse(item.PricingOption.Price.ToString());
                    orderTotal += (item.Count * decimal.Parse(item.PricingOption.Price.ToString()));

                    if (item.PricingOption.RequiresNotes)
                    {
                        if (!string.IsNullOrEmpty(orderNotes)) { orderNotes += "<br />"; }

                        orderNotes += "Order Notes For:" + item.PricingOption.Title;
                        orderNotes += "<br />";
                        orderNotes += item.OrderNotes;
                    }
                }
                else
                {
                    orderDetail.UnitPrice = item.Product.Price;
                    orderTotal += (item.Count * item.Product.Price);
                }                
                
                order.OrderDetails.Add(orderDetail);

            }

            // Set the order's total to the orderTotal count
            order.Total = orderTotal;

            order.OrderNotes = orderNotes;

            // Save the order
            _storeService.CreateOrder(order);

            // Empty the shopping cart
            EmptyCart();

            // Return the OrderID as the confirmation number
            return order.OrderID;
        }

        // We're using HttpContextBase to allow access to cookies.
        public string GetCartID(HttpContextBase context)
        {
            if (context.Session[CartSessionKey] == null)
            {
                if (!string.IsNullOrWhiteSpace(context.User.Identity.Name))
                {
                    context.Session[CartSessionKey] = context.User.Identity.Name;
                }
                else
                {
                    // Generate a new random GUID using System.Guid class
                    Guid tempCartID = Guid.NewGuid();

                    // Send tempCartID back to client as a cookie
                    context.Session[CartSessionKey] = tempCartID.ToString();
                }
            }

            return context.Session[CartSessionKey].ToString();
        }

        // When a user has logged in, migrate their shopping cart to
        // be associated with their username
        public void MigrateCart(string userName)
        {
            var cartItems = _storeService.GetCart(ShoppingCartID);

            foreach (var item in cartItems)
            {
                item.CartID = userName;
                _storeService.EditCartItem(item);
            }
        }
    }
}